import React, { forwardRef, useEffect, useImperativeHandle, useRef } from "react"
import { View, Input, Image } from "@tarojs/components"
import Icon from "@/components/GpFontIcon"
import Taro, { nextTick } from "@tarojs/taro"
import { useSetState } from "@/utils/hooks"
import { replyComment, uploadV4 } from "@/apis/yikao-community"
import { requestIsFullfilled } from "@/utils/request"
import { authActionHandler } from "@/utils/app"
import clsx from "clsx"
import styles from "./index.module.scss"
import { Backdrop } from "@taroify/core"

type IState = {
  value: string
  image: string
  imageId?: number
  keyboardHeight: number
  inputFocused: boolean
  openBackdrop: boolean
}
/**
 * @component GpCommentSender
 * 评论输入控件
 */
export default forwardRef(function GpCommentSender(
  {
    className,
    style,
    placeholder = "发条评论分享一下你的想法吧!",
    topCommentAction,
    onConfirm
  }: ICommentSendernProps,
  ref
) {
  const hideKeyboardHeight = -520
  const [state, setState] = useSetState<IState>({
    value: "",
    image: "",
    keyboardHeight: hideKeyboardHeight,
    inputFocused: false,
    openBackdrop: false
  })

  /** 是否是顶级评论(如 点评笔记, 点评资讯)*/
  const isTopCommentRef = useRef(false)
  /** 父级 ID，即：对谁的回复/点评 */
  const parentIdRef = useRef<number | undefined>()
  /** 当前回复的目标评论所属的评论id(一般如果是对顶级评论的回复, 为0, 否则为一级评论的id) */
  const ownParentIdRef = useRef<number | undefined>()
  const keyboardHeightRef = useRef<number>(0)
  const keyboardEventBind = useRef<boolean>(false)
  const blurTriggeredByMaskRef = useRef<boolean>(false)
  useEffect(() => {
    if (keyboardEventBind.current) return
    keyboardEventBind.current = true
    Taro.onKeyboardHeightChange(result => {
      if (result.height <= 0) {
        blurTriggeredByMaskRef.current = true
        setState({
          keyboardHeight: hideKeyboardHeight,
          inputFocused: false
        })
      }
    })
  }, [])
  useImperativeHandle<unknown, ICommentSendernRef>(
    ref,
    () => {
      return {
        triggerComment: function _triggerComment(
          parentId?: number,
          isTopComment?: boolean,
          ownParentId?: number
        ) {
          const handler = () => triggerComment(parentId, isTopComment, ownParentId)
          authActionHandler(handler, {
            avatarAndNickname: true,
            mobile: true
          })
        },
        handleClickTopComment
      }
    },
    []
  )
  function handleUpload() {
    blurTriggeredByMaskRef.current = true
    setState({ inputFocused: false, keyboardHeight: hideKeyboardHeight })
    Taro.chooseImage({
      count: 1,
      success(result) {
        const filepath = result.tempFilePaths[0]
        uploadV4(filepath).then(res => {
          if (res.data) {
            const resData = JSON.parse(res.data)
            if (resData.success) {
              setState({
                image: resData.data.image,
                imageId: resData.data.id,
                // 点击上传会收起键盘，上传成功后主动弹起即可
                inputFocused: true,
                keyboardHeight: keyboardHeightRef.current
              })
            }
          }
          blurTriggeredByMaskRef.current = false
        })
      },
      fail() {
        setState({ inputFocused: true, keyboardHeight: keyboardHeightRef.current })
        blurTriggeredByMaskRef.current = false
      }
    })
  }
  function handleConfirm() {
    const value = state.value.trim()
    if (!value) {
      Taro.showToast({
        title: "评论内容不能为空",
        icon: "none"
      })
      return
    }
    const fileIds: number[] = []
    if (state.imageId) {
      fileIds.push(state.imageId)
    }
    if (isTopCommentRef.current) {
      if (typeof topCommentAction === "function") {
        topCommentAction({
          content: value,
          fileIds
        }).then(res => {
          if (requestIsFullfilled(res)) {
            Taro.showToast({
              title: "评论成功",
              icon: "none"
            })
            afterComment()
            onConfirm && onConfirm(0, res.data.data, 0)
          }
        })
      }
    } else {
      replyComment({
        content: value,
        parentId: parentIdRef.current as number,
        fileIds
      }).then(res => {
        if (requestIsFullfilled(res)) {
          Taro.showToast({
            title: "评论成功",
            icon: "none"
          })
          onConfirm &&
            onConfirm(
              parentIdRef.current as number,
              res.data.data,
              ownParentIdRef.current as number
            )
          afterComment()
        }
      })
    }
  }
  function afterComment() {
    setState({
      image: "",
      imageId: void 0,
      inputFocused: false,
      value: "",
      keyboardHeight: hideKeyboardHeight
    })
    isTopCommentRef.current = false
    parentIdRef.current = void 0
    ownParentIdRef.current = void 0
  }
  /**
   * 触发抬起评论输入框
   * @param [parentId] 父级 ID，即：对谁的回复/点评
   * @param [isTopComment] 是否是顶级评论(如 点评笔记, 点评资讯),而不是对他人的回复
   * @param [ownParentId] 当前回复的目标评论所属的评论id(一般如果是对顶级评论的回复, 为0, 否则为一级评论的id)
   */
  function triggerComment(parentId?: number, isTopComment = false, ownParentId?: number) {
    parentIdRef.current = parentId
    ownParentIdRef.current = ownParentId
    isTopCommentRef.current = isTopComment
    const patch: Partial<IState> = { inputFocused: true }
    if (keyboardHeightRef.current) {
      patch.keyboardHeight = keyboardHeightRef.current
    }
    setState(patch)
  }
  function handleClickTopComment() {
    const handler = () => triggerComment(0, true, 0)
    authActionHandler(handler, {
      mobile: true,
      avatarAndNickname: true
    })
  }
  function handleRemoveImage(ev: any) {
    ev.stopPropagation()
    ev.preventDefault()
    setState({ image: "", imageId: void 0, inputFocused: false })
    nextTick(() => {
      setState({ keyboardHeight: keyboardHeightRef.current, inputFocused: true })
    })
  }
  function handleClickBackdrop() {
    blurTriggeredByMaskRef.current = true
    setState({ inputFocused: false, keyboardHeight: hideKeyboardHeight })
  }
  function handleInputBlur(ev: any) {
    ev.stopPropagation()
    ev.preventDefault()
    if (!blurTriggeredByMaskRef.current) {
      setState({ inputFocused: true, keyboardHeight: keyboardHeightRef.current })
    }
    blurTriggeredByMaskRef.current = false
  }
  return (
    <React.Fragment>
      <Backdrop
        className={styles.backdrop}
        open={state.keyboardHeight !== hideKeyboardHeight}
        closeable={false}
        onClick={handleClickBackdrop}
        onTouchStart={handleClickBackdrop}
      ></Backdrop>
      <View
        className={clsx(styles.opinionControl, className)}
        style={{
          bottom: state.keyboardHeight + "px",
          ...style
        }}
      >
        <View className={styles.sendControl}>
          <View className={styles.inputWrap}>
            <Input
              placeholder={placeholder}
              focus={state.inputFocused}
              adjustPosition={false}
              alwaysEmbed={false}
              className={styles.inputControl}
              value={state.value}
              onInput={ev => setState({ value: ev.detail.value })}
              onFocus={ev => {
                if (!keyboardHeightRef.current) {
                  keyboardHeightRef.current = ev.detail.height
                }
                setState({ inputFocused: true, keyboardHeight: ev.detail.height })
              }}
              onBlur={handleInputBlur}
              confirmHold
              holdKeyboard
              onConfirm={handleConfirm}
            />
            <Icon
              icon="icon-tupian"
              color="#999999"
              size={44}
              styles={{
                flex: "none"
              }}
              onClick={handleUpload}
            />
          </View>
          <View className="flex-none box-border">
            {state.value && (
              <View className={styles.sendBtn} onClick={handleConfirm}>
                发送
              </View>
            )}
          </View>
        </View>
        <View className="box-border">
          {state.image && (
            <View className={styles.contentShow}>
              <View className={styles.imageWrap}>
                <Image src={state.image} className={styles.image} />
                <Image
                  src="/images/yikao-community/del.png"
                  className={styles.delIcon}
                  onClick={handleRemoveImage}
                />
              </View>
            </View>
          )}
        </View>
      </View>
    </React.Fragment>
  )
})
